• a new predicate called op_oracle/2. The first argument is a description of what you are interested in finding out about. The second argument will be a property.
At present, op_oracle can be asked about files and folders. It recognises items of the following type:
file(Name) %the file is assumed to be in the current folder
folder(Volume,Directory)
file(folder(Volume,Directory),Name)
indexed_file(folder(Volume,Directory),I) %i.e. the I-th file in the folder
the properties returned can be inspected by resatisfying the goal.
e.g.
current_folder(F),current_property(indexed_file(F,1),P). %information about the first indexed file in the current folder.
• user hooks. At four specific times during Open Prolog's operation - start, restart, abort and halt times - the system looks for user hooks and executes them if they exist. This feature might be useful, for instance, if you wanted something done every time the program was aborted, or just before restarting after abort.
To use them, define clauses of the form:
user_hook(<kind>) :- <whatever you want to do>.
where <kind> must be one of the following four atoms:
start
restart
abort
halt
e.g. user_hook(halt) :- play('Wild Eep',0).
• Stream IO - New IO predicates for dialogs and apple events
A new IO architecture is being developed. It will be ISO Prolog compliant. At present, it must coexist with the existing IO architecture, which is gradually being phased out. All new IO predicates have the prefix 'stream_', so they are called 'stream IO predicates'. They are useful for dialogs and apple events.
Here is a list of stream IO predicates defined so far:
stream_get_size(Stream,Size)
stream_flush_output %current stream assumed
stream_close(Stream)
stream_get(Byte)
stream_set_input(Stream)
stream_put(Byte)
stream_set_output(Stream)
stream_get_position(Stream,Position)
stream_set_position(Stream,Position)
stream_current_input(Stream)
stream_current_output(Stream)
stream_write(Term) %to current output stream
stream_writeq(Term)
stream_read_term(Stream,Term,Options) %standard ISO options for variables only
stream_nl.
They are somewhat like their ISO equivalents, but they don't throw errors or report properties correctly.
There a number of caveats:
1. When the new IO system finally replaces the old, the prefix stream_ will be dropped.
2. The stream_read_term/3 predicate uses strict minimal ISO Prolog syntax - that means no accented characters, nothing beyond standard ASCII, and no control characters.
3. the predicate stream_read_term is slow and bulky, because it is all still written in Prolog; even the tokeniser state machine is emulated in Prolog.
You use special predicates to open these new-fangled streams - see below in dialogs and apple events.
•Stream IO to dialog items.
(Note: to use these facilities, you must have the Open Prolog extension files called 'Stream Read' and 'Stream Write' in your Open Prolog Additions folder.)
These extension files are available at the Open Prolog FTP site.
You can now open dialog editText or staticText items as IO streams and read and write them as normal streams, using the new stream IO predicates. To open a dialog item as a stream, use something like the following example, where we suppose the dialog is dialog 3 (from new_dialog) and the item is item 4:
dialog_item_stream_open(3,4,0,0,read,IStream).
IStream will be unified with the stream from which you can read the text of the item, which must be staticText or editText.
•Apple Events.
(Note: to use these facilities, you must have the Open Prolog extension files called 'Stream Read' and 'Stream Write' in your Open Prolog Additions folder.)
These extension files are available at the Open Prolog FTP site.
OP now responds to a single type of apple event - the 'do script' apple event. This is very experimental - please report your experiences with it.
The string of text you send as an argument becomes the input stream. In the simple example, it is taken as a simple query by Open Prolog and executed. No variable bindings are returned and it can't be resatisfied.
The following account assumes you have consulted the sample file:
'Apple Event Handler'
Here's how an apple event would look, using Apple's Script Editor:
tell application "Open Prolog"
do script "beep,stream_write(hi). "
end tell
(This script should be in the Apple Event sample folder too.)
Note: notice how the dot at the end is followed by a space (a return would be OK too, but not a tab!) - this is to comply with the strict definition of an end token in ISO Prolog.
What happens is this:
When OP receives the apple event, it generates an interrupt request. In response to the interrupt, the apple event handler is executed. The sample apple event handler supplied opens two I/O streams with the new built-in predicate: open_apple_event_streams/2. The first stream contains the incoming text, the second stream will be used to send reply text. The handler then sets current input and output to point to these streams and tries to read and execute the incoming text. Any errors thrown (except system errors) are trapped and written to the output stream. On completion of the execution of the incoming queries, the streams are closed (closing the output stream acknowledges the apple event) and the interrupt exits. All IO with the streams is stream IO.
•dialog toolbox additions
The dialog toolkit can handle simple scrollbars and simple popup menus. See the dialogs folder for more information.
• The term reader (i.e. read/1, get/1 and get0/1) now throws syntax errors for you to catch.
• In addition, a new read_term/2 introduced. This is of the form read(Term,OptionList) where OptionList may be empty.
The following ISO Prolog options are recognised:
* variables(Vl), %action: a list of variables is given in order of discovery.
* variable_names(VN_List), %action: a list of pairs of variables and their names is formed. The elements are of the form V=A there V is the variable and A is the variable's name, expressed as an atom.
* singletons(VN_List), %as above, but restricted to variables that occur only once in the term read.
The following extra options are recognised:
* progress_indication(Boolean) %action: if boolean is true, then upon reading a term, the progress bar ratio is set to the ratio of the current file position to the file size. To see it, of course, you must have already done a 'system$show$progress'. Afterwards, you can hide it again with 'system$hide$progress'. (Doesn't work for the 'user' ersatz file).
* recover_after_syntax_error(Boolean) %action, if Boolean is true, then, if a syntax error occurs, the appropriate action will be taken (error message etc.) and another term will be read before returning to the caller. Useful if you want to read a term and not have to catch syntax errors yourself.
• The text editor understands bracket balancing: double click on a bracket to select everything between it and its corresponding bracket - works for ( ) [ ] and { }, and also these pairs: « » ‘ ’ and “ ”.
• A dialog toolkit is currently being added. See a separate folder called Dialogs.
• User-added menus, the Quit menu item in the File menu and all the items under the Prolog menu are now continuously activated, being serviced by interrupt handlers within Open Prolog. Hitherto, Open Prolog had to be reading for the menu action to be recognised.
• Following a discussion about 'defining' predicates on comp.lang.prolog, Open Prolog now distinguishes between 'defined' and 'undefined' predicates in a way that seems to be a standard among recent Prolog implementations, as follows:
A user predicate is defined by asserting clauses for that predicate, or by declaring the predicate to be 'dynamic' with the :-dynamic(Functor/Arity) directive. For example,
:-dynamic(a/0).
will 'define' the predicate a/0, though it adds no clauses.
An existing predicate is undefined by abolishing it with abolish(Functor,Arity). For example:
abolish(a,0).
will remove all the clauses for the predicate a/0 and will also undefine it.
Note that retract/1 never undefines a predicate.
So, a predicate can be
1. defined, with clauses;
2. defined, with no clauses;
3. undefined, with no clauses.
If a call is made, one of the three above cases holds. Case 1 is normal. In case 2, the call will simply fail. In case 3, the behaviour of the interpreter depends on the setting of the 'unknown' flag (use unknown(CurrentFlag,NewFlag) to find out). If the 'unknown' flag is 'fail', then the call will just fail; if the 'unknown' flag is 'trace' then the debugger will be called.
Some predicates may legitimately have no clauses in them at a particular time, and calls to them should simply fail, even when the unknown flag is set to 'trace'. Those predicates can be 'defined' by declaring them to be dynamic.
It is useful when debugging programs to set the 'unknown' flag to 'trace' so that you're notified if there are any undefined predicates being called. Using dynamic/1, you can ensure that calls to predicates that legitimately have no clauses in them will not result in calls to the debugger.
• copy_term/2 added.
• in the light of a discussion on comp.lang.prolog about 'all solutions', bagof/3 has been modified to comply with the ISO Standard regarding the order in which solutions appear in the solution list in the presence of free variables. Specifically, the order of the solutions is the order in which they are discovered. Hitherto, the order was somewhat unpredictable.
• Drag and drop support has been added. Every drag is a _copy_, never a _move_ because the undo mechanism needs to be updated to accommodate undo-able moves.
• Speed - many simple built-ins have been greatly speeded up, and other components tuned up. You can expect a speed improvement of 10% to 20% in general work.
• in compliance with the ISO draft, close/1 _never_ returns an error and always succeeds.
• for compatability with other prologs, statistics/2 has been added.
E.g. statistics(runtime,X) will return X unified with a list containing runtime
and time since the last 'statistics' call.
• the built-in statistics/0 has been modified to look more like other prologs.
• what was called gc in Open Prolog has been renamed garbage_collect for compatability.
••Bug Fixes & Improvements
• fixed a bug in throwing errors from zero-arity built-in predicates.
• various annoying little format bugs fixed on the text editor, particularly after changing font or font size.
• the scroll bars now track text scrolling caused by a drag.
• fixed a bug parsing say 8','abc. The 8'… looks like the start of a bse-8 number that has no digits. It caused the parser to crash. Now, the parser recovers to parse i as 8 , abc. Also, the term writer now puts in a space where an ambiguity would arise with a single digit followed by a quoted number. (1.0.3d31)
• fixed a bug in the emulator causing an occasional failure to fully dereference a variable before using it (varVar). (1.0.3d30)
• fixed a bug that allowed a list to contain no arguments even though it had commas. E.g. it would accept a([,,,,]) as a([]). A benign but annoying little bug. (1.0.3d30)
• ignore a bogus (?) error code returned by the cursor traps (7.5.3 with Debugging Memory Manager 1.0.5)
• read/2 is renamed read_term/2 for compatability with ISO Prolog.
• OP no longer recognises, say, [a,..b] as [a|b].
• A memory leak in the Dialog Toolkit has been fixed. There are other small ones, and they will be fixed over time.
• A possible bug (never reported) in the memory allocator fixed. If an attempt was made to allocate more memory to the stacks, and if the allocation failed, then an error message would be given, but OP would continue as if the extra memory was there…
• Fixed a front-window highlighting error with the find/replace menus.
• OP is now a bit smarter at deciding whether it's in the background or foreground; it uses the Process Manager now, if present.
• Better system error messages.
• Fixed a bug in retract/1 introduced when removing another bug (see below). Fixed in 1.0.3d25.
• Fixed a few missing pictures in 'Getting Started' Thank you m***os**t - not.
• Fixed a few errors in the documentation and in the Dialog Samples code.
• Fixed a bug with menu highlighting - it was left on when a control panel item was selected using hierarchical menus (Fixed in 1.0.3d24)
• Fixed an infelicity in the arrow keys. If there is a non-empty selection, the left arrow/right arrow merely now just the caret to the left or right end as appropriate. Also, pressing the down arrow moves the caret one line down from the _end_ of the selection. (This is similar to most word and text processors and is not done automatically by TextEdit, the underlying text manager). (Done in 1.0.3d24)
• Fixed another infelicity with autoindent. If you used autoindent to automatically indent a line that began with with spaces and tabs, they were left in place, so the text wasn't lined up properly. (Fixed in 1.0.3d24)
• Fixed a bug in retract/1 - if it failed, it left garbage collection switched off (fixed in 1.0.3d23).
• Fixed bugs with handling the resource needed to store a window's position information. Occasionally it may have crashed the machine.
• The debugger has always used the print/1 predicate for writing the predicate involved in the call/exit/redo/exit, so you can substitute what you like with portray/1. If you don't have your own portray clauses, the debugger now uses writeq/1 rathar than write/1.
• DCG expander now handles -> and \+ ¬ and not/1 properly, and expands variables on rhs as calls to phrase/3.
• fixed bug whereby Open Prolog stayed open, with no worksheet open (so you couldn't easily quit from it) after asking it to print documents from the desktop.
• fixed bug in current_op whereby it would not agree that a postfix operator had been defined.
• fixed bug in bagof/findall/setof when the item to be kept is a variable. What was happening was that all the variables were unified together. Huh.
• fixed bug in write where a term of the form $VAR(N) was to be written. If N is an integer, this term prints as a variable name. If not, write/1 was aborting.
• various garbage collection bugs fixed (1.0.3d18 & 1.0.3d19)
• a bug causing some menu items to disappear has been fixed (1.0.3d17)
• a bug causing OP to hang when asked for the length of a list of indeterminate length has been fixed. It also caused =../2 to hang if both arguments were variable
• some arithmetic overflow checks have been tightened up
• you can really close windows in System 6 non-multifinder systems now. (1.0.3d16)
• following a discussion on comp.lang.prolog about all solutions, bagof has been modified to comply with the ISO Standard regarding the order in which solutions are proposed in the presence of free variables. (1.0.d15)
• various crash bugs on 68000 machines running System 6 fixed. (1.0.3d15)
• calculation of memory allocation on the About… Screen has been fixed for 68000 based machines. (1.0.3d15)
• a cause of crashes on machines without drag and drop has been fixed (1.0.3d14)
• the ersatz file 'user' can now be consulted and reconsulted from as before.
• an initialisation race condition which caused crashes on faster Macs - e.g. LC 475/ LC 630s has been removed.
• when writing output, an automatic space incorrectly inserted between punctuation and other symbol characters was causing trouble - e.g. if read back in, a dot followed by a space before something else was being treated as an end-of-clause marker. This has been fixed.
• Consult and reconsult each had a bogus backtrack point (apart from open/3) - removed.
• open/3 had a bogus backtrack point in read mode - removed.
• on abort or on exit from the Open Prolog System Error dialog, open streams are flushed and closed.
• Fixed various bugs occuring when run from a shared volume, a locked volume (e.g. CD-ROM), or in a system with a locked or invisible System Folder
• Command-dot is more robust. The user_interrupt it threw was sometimes absorbed when nofileerrors was active and the interrupt was thrown up through a file handling predicate.
• numbervars/3 has been changed to replace variables with the terms '$VAR(N)' where N is an integer from 0 upwards in left to right traversal order. Predicates write and writeq have been modified to output atoms starting at A, B, C and so on, A1, B1, C1 etc whenever the term '$VAR(N)' occurs in a term to be written (see the ISO Prolog Draft for details). So, overall, the effect of using numbervars and write is the same as before. What's important though is that then internal arrangments, which were awful beyond belief, and which occasionally caused gc problems, are now regularised.
Version 1.0.2
Big News
• Open Prolog runs on the Power Macs. Hold on, though, it runs in emulated mode, so it doesn't exactly race along. To be exact, on a prerelease 8100/80, it ran naive reverse at 21kLips (about three times a IIx). All the same, it's heartening.
•• Bug Fixes & Improvements
• Some changes have been made to the handling of unexpected end of file conditions, to try to improve error detection.
• On Quadra 660AVs, OP seemed to run out of scratch memory. This has been cured by increasing the amount of scratch memory reserved at startup. OP is not smart about memory demands for opening windows or consulting documents; if there isn't enough memory allocated, OP is unable to get any more and may get into trouble as a consequence.
• Sometimes, in System 7, OP didn't figure out which folder was the current folder. This bug has been present in all versions that run under System 7, and may have been the cause of some mysterious problems.
• When a file is being consulted or reconsulted, all directives - goals preceded by :-, are executed. This idea is now extended to include calls preceded by ?-, so that goals preseded by ?- in a file being consulted or reconsulted will also be executed.
• A bug which crashed the machine when a quote was preceded by a digit and followed by other than a digit was fixed. The bug was introduced when OP became capable of using bases other than 10.
• OP now recognises a number specification of the form 0'<character> as being an integer whose value is the character code of <character>. For example, if you entered:
X is 0'a.
you'd get X = 97 (the character code for 'a').
• OP has stopped complaining about an empty list with white space in it.
• Sometimes it is impossible to assert a given clause, either because an attempt is made to redefine a built-in predicate or because some part of the body is illegal (e.g. an integer call). OP now (at least) reports the clause and the kind of error.
• OP would only consult or reconsult an open window if the file in the window happened to be in the home folder. This restriction has been removed.
• If a file is open in a window, OP will ask you if it's OK to close it if it's to be written to, and will ask you if it's OK to save it before opening it for reading.
•• New features.
Many big changes have occured beneath the surface of Open Prolog - all for the better, and all compatible with previous versions.
- Many of Open Prolog's built-in predicates are themselves written in Prolog and compiled. The biggest internal change has been a significant revision to the compiler, linker and loader which collectively had a 64 kByte limit, causing much grief. This limit has now been removed, and the loading procedures have been modified to offer greater flexibility.
- Open Prolog checks a special folder, called Open Prolog Additions, in the Extensions Folder (or the System Folder in System 6). External Predicates, separately compiled Prolog code, and other Macintosh Resources can be placed in Open Prolog extension files. These files have a distinctive Open Prolog icon and, if placed in the Open Prolog Additions Folder, are opened for use at startup. In addition, if a file called 'Open Prolog Options' can't be found in the Startup Folder, it will be consulted if it's present in Open Prolog Additions.
There are two extension files with this release of Open Prolog:
'Environment' implements a suggestion of Richard O'Keeffe's providing details of the Prolog environment in a standard way by making calls to environment/1.
'debugStartAction' prints the date and time at the start of a trace session.
- A new way of specifying files and folders, based on the Macintosh File Specification, has been developed.
The full, canonical, specification of a folder is now:
folder(VolumeNumber,IndexNumber).
A number of standard folders have special 4-letter abbreviations, and these abbreviations can be used instead of the folder specification given above. The four standard folder abbreviations supported directly by Open Prolog are:
'Strt' - Startup Folder. This is the folder containing Open Prolog itself.
'Home' - Home Folder. This is the folder initially containing the Open Prolog Worksheet.
'Addn' - Additions Folder. This is the folder 'Open Prolog Additions' contained in the Extensions Folder (the System Folder for System 6).
'Curr' - Current Folder. Initially the Home Folder, this can be set using the set_folder predicate.
Under System 7, Open Prolog also recognises all System 7 abbreviations for special folders, including such useful ones as 'desk' for the desktop, 'macs' for the System Folder, 'temp' for the Temporary Items folder, and many others.
The canonical specification of a file is now:
file(<FolderSpecification>,Name)
where <FolderSpecification> is as described above. Whenever a file is to be used, the specification you give is resolved to the standard, and is then used.
If you specify a file simply by giving its name, then it is expected to be in the current folder. Partial pathnames and full pathnames are resolved correctly.
- New file handling predicates. These are based loosely on some of the ISO draft I/O predicates and use the new file specification scheme described above. Note that the name of standard input and output is simply 'user', not 'user_input' or 'user_output'.
The new predicates are:
open(FileSpec,Mode,Stream)
FileSpec is anything sensible, e.g. a full file specification, just an name,
or a folder and name
Mode is read, write or append
Stream is either an automatically generated Stream ID - an integer - or an atom
of your choosing (the atom mustn't be the Stream ID of another stream).
The file specified is opened, but the stream doesn't become the current input or
output stream automatically.
close(Stream)
set_input(Stream)
set_output(Stream)
current_input(Stream)
current_output(Stream)
canonicalFileSpec(FileDescription,FileSpec).
returns the canonical specification of the item described in the FileDescription. If the item is a folder, then a canonical folder description is returned. If the item is a file, the canonical file description is returned, including the file's name correctly capitalised just as it appears in the finder.
If errors occur and fileerrors are enabled, the error terms are thrown.
If errors occur when fileerrors are disabled, the predicates fail quietly.
- New window handling predicates.
open_window(FileSpec,Window,CloseAction)
The file specified is opened into the Window whose index number is returned. The normal close action to specify is confirm_close - the user will then be asked whether to save a changed window before closure. If you specify dont_confirm_close, the file will be saved automatically on closure.
If the file is already open in a window, no new window is opened; instead the old window is brought to the front.
window_property(Window,Property).
This is modelled on stream_property/2 and discloses the following properties: window_name(Name) file_attached(Boolean) file_spec(FileSpec) file_and_window_contents_match(Boolean) (this will be false if the window is 'dirty'). The last two properties are not disclosed if no file is attached.
read_with_progress(X) ###note - this is gone, use read(Term,Options) instead. See d27 release notes.